//
// Store.cs
//
// Copyright (C) 2008 Lukas Lipka <lukaslipka@gmail.com>
//

using System;
using System.IO;
using System.Collections.Generic;

using Mono.Data.Sqlite;
using Dashboard.Util;

namespace Dashboard.Engine.Fidelity {

	public class Store : IDisposable {
		
		// 1: Initial version
		private const int VERSION = 1;
		
		private string store_path = null;
		private string store_db = null;
		private string store_fingerprint = null;

		private SqliteConnection connection = null;

		private SqliteCommand get_location = null;
		private SqliteCommand set_location = null;

		public Store ()
		{
			this.store_path = Path.Combine (PathFinder.UserData, "Fidelity");
			this.store_db = Path.Combine (store_path, "Store.db");
			this.store_fingerprint = store_db + ".fingerprint";
		}

		public void Initialize ()
		{
			if (!Directory.Exists (store_path))
				Directory.CreateDirectory (store_path);

			Open ();
			PrecompileCommands ();
		}

		public void Dispose ()
		{
			if (connection != null)
				connection.Dispose ();
		}

		private void Open ()
		{
			// Check our store fingerprint file version to see
			// if our database format is up to date - if not
			// purge the database.

			bool create_tables = false;

			if (File.Exists (store_fingerprint) && File.Exists (store_db)) {
				string version = File.ReadAllText (store_fingerprint);
				
				if (String.IsNullOrEmpty (version) || Int32.Parse (version) != VERSION) {
					Engine.Log.Warn ("Version mismatch - purging");
					create_tables = true;
					Purge ();
				}
			} else {
				Engine.Log.Debug ("Creating new store");
				create_tables = true;
				Purge ();
			}

			try {
				connection = new SqliteConnection ();
				connection.ConnectionString = "URI=file:" + store_db;
				connection.Open ();

				if (create_tables == true) {
					CreateTables ();
				}
			} catch (Exception e) {
				Engine.Log.Error ("Failed to open metadata store");
				Engine.Log.Error (e);
				connection = null;
			}

			if (!File.Exists (store_fingerprint)) {
				File.WriteAllText (store_fingerprint, VERSION.ToString ());
			}
		}

		private void CreateTables ()
		{
			// FIXME: Store information like time of day, essid, etc.

			SqliteCommand command = new SqliteCommand (connection);
			command.CommandText = "CREATE TABLE Locations (name TEXT, mac TEXT)";
			command.ExecuteNonQuery ();
		}

		private void PrecompileCommands ()
		{
			set_location = new SqliteCommand (connection);
			set_location.CommandText = "INSERT INTO Locations VALUES (@name, @mac)";

			get_location = new SqliteCommand (connection);
			get_location.CommandText = "SELECT name from Locations WHERE mac=@mac";
		}

		public void Purge ()
		{
			if (connection != null)
				connection.Dispose ();

			if (File.Exists (store_db))
				File.Delete (store_db);

			if (File.Exists (store_fingerprint))
				File.Delete (store_fingerprint);				
		}

		public void SetLocation (string name, string mac)
		{
			lock (connection) {
				set_location.Parameters.AddWithValue ("@name", name);
				set_location.Parameters.AddWithValue ("@mac", mac);
				set_location.ExecuteNonQuery ();
			}
		}

		public string GetLocation (string mac)
		{
			lock (connection) {
				get_location.Parameters.AddWithValue ("@mac", mac);
				
				using (SqliteDataReader reader = get_location.ExecuteReader ()) {
					reader.Read ();
					return reader.GetString (0);
				}
			}
		}
	}
}
